﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.Management;
using System.Runtime.InteropServices;

namespace RedFlag
{
    public delegate void ChooseProcessEventHandler(object o, RunningProcessEventArgs e);
    public delegate void DetectProcessEventHandler(object o, RunningProcessEventArgs e);
    public partial class ChooseProcess : Form
    {
        public event ChooseProcessEventHandler ProcessChosen;
        public event DetectProcessEventHandler ProcessDetected;
        public ChooseProcess()
        {
            InitializeComponent();

        }
        
        protected void onProcessChosen()
        {
            RunningProcessEventArgs args = new RunningProcessEventArgs();
            args.ProcessName = (string)dgvProcesses.SelectedRows[0].Cells[1].Value;
            args.ProcessId = (int)dgvProcesses.SelectedRows[0].Cells[2].Value;
            if (ProcessChosen != null) ProcessChosen(this, args);
        }

        private void butOK_Click(object sender, EventArgs e)
        {
            onProcessChosen();
            this.Close();
        }

        private void butCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void PopulateRunningProcesses()
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process process in processes)
            {
                RunningProcessEventArgs args = new RunningProcessEventArgs();
                args.ProcessName = process.ProcessName;
                args.ProcessId = process.Id;
                if (args.ProcessId == Process.GetCurrentProcess().Id) continue; // can't attach to yourself - you will go blind
                    try
                    {
                       // if (!process.HasExited)
                      //  {
                            bool is32Bit = true;
                            IsWow64Process(GetProcessHandleVistaPlus(process.Id), out is32Bit); // only show things we can debug
                            if (is32Bit ^ IntPtr.Size == 8)
                            {
                                //args.ImagePath = process.MainModule.FileName;
                                args.ImagePath = GetExecutablePathVistaPlus(process.Id);
                                if (!String.IsNullOrEmpty(args.ImagePath)) args.IconImage = ShellIcon.GetIcon(args.ImagePath, false);
                                else args.IconImage = ShellIcon.GetIcon(System.IO.Path.Combine(Environment.SystemDirectory, "cmd.exe"), false);
                                /* BD- this bit will add the application pool name to w3wp processes */
                                if (args.ImagePath.ToUpper().Contains("W3WP"))
                                {
                                    string wmiQuery = string.Format("select CommandLine from Win32_Process where ProcessId='{0}'", process.Id);
                                    ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery);
                                    ManagementObjectCollection collection = searcher.Get();
                                    foreach (ManagementObject instance in collection)
                                    {
                                        string appPoolName = "unknown app pool";
                                        try
                                        {
                                            string[] argString = ((string)instance["CommandLine"]).Split(' ');
                                            for (int i = 0; i < argString.Length; i++)
                                            {
                                                if (argString[i].ToLower() == "-ap")
                                                {
                                                    appPoolName = String.Empty;
                                                    while (!argString[i + 1].StartsWith("-"))
                                                    {
                                                        appPoolName += argString[i + 1].Trim('\"');
                                                        i++;
                                                    }
                                                    break;
                                                }
                                            }
                                            args.ProcessName += " [" + appPoolName + "]";
                                        }
                                        catch {/*don't care */ }
                                    }
                                } /* END - W3WP stuff*/
                                onProcessDetected(args);
                       //     }
                        }
                    }
                    catch (Win32Exception)
                    {
                      //  args.ImagePath = "";
                        onProcessDetected(args);
                    }
            }
        }
        protected void onProcessDetected(RunningProcessEventArgs evArgs)
        {
            if (this.ProcessDetected != null)
            {
                ProcessDetected(this, evArgs);
            }
        }

        private void ChooseProcess_Load(object sender, EventArgs e)
        {
            this.ProcessDetected += new DetectProcessEventHandler(ChooseProcess_ProcessDetected);
            ThreadStart start = new ThreadStart(PopulateRunningProcesses);
            Thread t = new Thread(start);
            t.SetApartmentState(ApartmentState.STA);
            t.IsBackground = true;
            t.Name = "RedFlag_Processes";
            t.Start();
        }
        public delegate void ThreadSafeProcessDetected(object o, RunningProcessEventArgs e);
        void ChooseProcess_ProcessDetected(object o, RunningProcessEventArgs e)
        {
            if (this.dgvProcesses.InvokeRequired)
            {
                this.BeginInvoke(new ThreadSafeProcessDetected(ChooseProcess_ProcessDetected), o, e);
                return;
            }
            dgvProcesses.Rows.Add(e.IconImage, e.ProcessName, e.ProcessId);
        }

        private void dgvProcesses_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            onProcessChosen();
            this.Close();
        }
        private static IntPtr GetProcessHandleVistaPlus(int dwProcessId)
        {
            IntPtr hprocess = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, (int)dwProcessId);
            return hprocess;
        }
        private static string GetExecutablePathVistaPlus(int dwProcessId)
        {
            StringBuilder sb = new StringBuilder(1024);
           IntPtr hprocess=GetProcessHandleVistaPlus(dwProcessId);
            if (hprocess != IntPtr.Zero)
            {
                try
                {
                 int size = sb.Capacity;
                 if (QueryFullProcessImageName(hprocess,0,sb,ref size))
                   {
                    return sb.ToString();
                  }
                }
                finally
                {
                    CloseHandle(hprocess);
                }
            }
            return String.Empty;
        }
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(
             ProcessAccessFlags processAccess,
             bool bInheritHandle,
             int processId
        );
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags, [Out]StringBuilder lpExeName, ref int lpdwSize);
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);
        [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsWow64Process([In] IntPtr processHandle,
             [Out, MarshalAs(UnmanagedType.Bool)] out bool wow64Process);
    }
    [Flags]
    public enum ProcessAccessFlags : uint
    {
        All = 0x001F0FFF,
        Terminate = 0x00000001,
        CreateThread = 0x00000002,
        VirtualMemoryOperation = 0x00000008,
        VirtualMemoryRead = 0x00000010,
        VirtualMemoryWrite = 0x00000020,
        DuplicateHandle = 0x00000040,
        CreateProcess = 0x000000080,
        SetQuota = 0x00000100,
        SetInformation = 0x00000200,
        QueryInformation = 0x00000400,
        QueryLimitedInformation = 0x00001000,
        Synchronize = 0x00100000
    }
    public class RunningProcessEventArgs
    {
        private int m_ProcessId;
        private string m_ProcessName;
        private string m_ImagePath;
        public Icon m_Icon;
        public Icon IconImage
        {
            get
            {
                return m_Icon;
            }
            set
            {
                m_Icon = value;
            }
        }
        public string ImagePath
        {
            get
            {
                return m_ImagePath;
            }
            set
            {
                m_ImagePath = value;
            }
        }
        public string ProcessName 
        {
            get
            {
                return m_ProcessName;
            }
             set

            {
                 m_ProcessName=value;
            }
        }
        public int ProcessId
        {
            get
            {
                return m_ProcessId;
            }
            set
            {
                m_ProcessId = value;
            }
        }

    }
}
